<template>
<div>
	<el-popover
  ref="tip"
  placement="right-end"
  width="200"
  trigger="manual"
  v-model="visible">
  <div>
	  <div class="popover-header">
		  Tip
		  <i class="el-icon-close" @click="_ => visible = false"></i>
	</div>
	  {{tipMessage}}
  </div>
<el-select slot="reference" ref="select" :allow-create="allowInput" :filterable="allowInput" :placeholder="placeholder" :value="inputValue" @input="updateValue"  v-bind="$attrs" 
 :multiple='multiple'  v-on="$listeners" @focus="_ => visible = false">
		<!-- 这里的mouseover与 mouseup事件是为了防止在用户选择选项，鼠标按下还未放开时触发了el-select的blur事件（该事件会触发对值的校验）-->
		<el-option
		v-for="(item, index) in selectOptions"
		v-if="item.visible !== false"
		:key="index"
		@mouseover.native="disableEventBlur"
		@mouseup.native="enableEventBlur"
		:label="item.label"
		:value="item.value || item.label"
    :disabled="!editable">
		</el-option>
	</el-select>
	
</el-popover>
    <el-input v-if="isInput" placeholder="请填写" @input="updateInputValue" :value="elValue"/>
	</div>
</template>
<script>
import { exportWidthInfo } from "../../utils";
export default {
	name: "v-selectWithInput",
	props: {
		value: {
			type: [String, Array, Number],
			default: ""
		},
		options: {
			type: Object,
			required: true
		},
		editable: Boolean
	},
	data() {
		return {
			inputValue: this.value,
			allowInput: this.options.allowInput,
			placeholder:
				this.options.placeholder ||
				(this.options.allowInput ? "选择或输入" : "请选择"),
			multiple: this.options.multiple,
			selectOptions: this.options.options,
			label: this.options.label,
			select: null,
			tip: null,
			tipMessage: "",
			visible: false,
			changeOption: {
				enable: [],
				disable: []
			},
			disableOptions: [],
			oldDisableOptionsLength: 0,
			enableTimer: null,
			disableTimer: null,
			timer: null,
			onBlur: this.$listeners.blur,
			isInput: false,
			elValue: ""
		};
	},
	watch: {
		"changeOption.enable"() {
			this.timer && clearTimeout(this.timer);
			this.timer = setTimeout(() => {
				!this.select.value && this.showTip();
				this.changeOption.enable.length = 0; //这里用设置长度为0的方式，避免再次触发watch
				this.changeOption.disable.length = 0;
			}, 50);
		},
		"changeOption.disable"() {
			this.timer && clearTimeout(this.timer);
			this.timer = setTimeout(() => {
				!this.select.value && this.showTip();
				this.changeOption.enable.length = 0;
				this.changeOption.disable.length = 0;
			}, 50);
		}
	},
	methods: {
		disableEventBlur() {
			this.select.$off("blur");
		},
		enableEventBlur() {
			this.select.$on("blur", this.onBlur);
		},
		showTip() {
			let enable = "",
				disable = "";
			if (this.changeOption.enable.length) {
				enable = "‘";
				let labels = this.changeOption.enable.map(option => {
					return option.label;
				});
				enable += labels.toString() + "’已启用";
			}
			if (this.changeOption.disable.length) {
				disable = "‘";
				let labels = this.changeOption.disable.map(option => {
					return option.label;
				});
				disable += labels.toString() + "’已禁用";
			}
			this.tipMessage = "选项" + enable + disable;
			this.visible = true;
		},
		updateValue(val) {
			console.log(
				"this.options.showExtraInput",
				val,
				this.options.showExtraInput,
				val === this.options.showExtraInput
			);
			this.inputValue = val;
			if (val === this.options.showExtraInput) {
				this.isInput = true;
			} else {
				this.isInput = false;
				this.$emit("input", val);
				this.$nextTick(_ => this.$emit("blur")); //这里与其他基础组件不同，是在更新值得时候，手动触发blur事件去校验。因为此类选择性组件，在选择的同时，会触发blur,而此时表单值尚未更新（即验证先于值更新了），会导致验证始终是失败。
			}
		},
		updateInputValue(val) {
			this.$emit("input", val);
		}
	},
	mounted() {
		this.select = this.$refs.select;
		this.tip = this.$refs.tip;
	},
	created() {
		delete this.$listeners.input; //去掉对input事件的监听
		this.selectOptions.forEach(option => {
			if (option.rely && option.rely.visibility) {
				this.$watch(
					_ => option.visible,
					visible => {
						if (
							this.select.value == option.value ||
							(this.select.value == option.label &&
								visible == false)
						) {
							this.updateValue(); //抛出空值
							this.$nextTick(_ => {
								this.changeOption.disable.push(option);
							});
						} else {
							if (visible) {
								this.changeOption.enable.push(option);
							} else {
								this.changeOption.disable.push(option);
							}
						}
					}
				);
			}
		});

		this.$emit(
			"dispatch-width",
			exportWidthInfo(this.options.display, 120)
		);
		if (this.value) {
			let isExtra = !this.options.options.some(
				option =>
					option.value !== undefined
						? option.value == this.value
						: option.label == this.value
			);
			if (isExtra) {
				this.elValue = this.value;
				this.inputValue = this.showExtraInput;
				this.isInput = true;
			} else {
				this.inputValue = this.value;
			}
		}
	}
};
</script>
<style lang="less">
.popover-header {
	padding: 0 0 1rem 0;
	text-indent: -0.2rem;
	.el-icon-close {
		cursor: pointer;
		float: right;
	}
}
</style>
